package top.hekun.study.core;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.util.CheckClassAdapter;
import top.hekun.study.core.util.ClassFileUtil;
import top.hekun.study.core.visitor.simple.*;

import java.io.File;
import java.io.PrintWriter;
import java.util.Arrays;

/**
 * 〈ClassReader 读取文件 并简单修改文件〉 类修改简单演示
 *
 * @author: Sakura
 * @date: 2023/5/7
 */
public class ClassSimpleModifyClassDemo {
    // 是否开启检查
    private static final boolean CHECK = false;
    // 是否开启 进行中检查
    private static final boolean HAVE_IN_HAND_CHECK = false;
    // 是否开启结束检查
    private static final boolean END_CHECK = false;
    // 是否伪造错误
    public static final boolean ERROR_CODE = false;


    public static void main(String[] args) {

        byte[] classBytes = ClassFileUtil.getClassFileByteToClassName("HelloWord");
        ClassReader classReader = new ClassReader(classBytes);
        System.out.println("access > " + classReader.getAccess());
        System.out.println("className > " + classReader.getClassName());
        System.out.println("classSuperName > " + classReader.getSuperName());
        System.out.println("Interfaces > " + Arrays.toString(classReader.getInterfaces()));
        System.out.println();

        ClassVisitor classVisitor;
        // 类编写器
        ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
        // 方法检查 在 MyClassVisitor6 中查到错误
        classVisitor = classWriter;
        if (CHECK && HAVE_IN_HAND_CHECK) {
            classVisitor = new CheckClassAdapter(classWriter);
        }
        int apiVersion = Opcodes.ASM9;
        // 更改类的版本
        classVisitor = new MyClassVisitor1(apiVersion, classVisitor);
        // 更改类的接口
        classVisitor = new MyClassVisitor2(apiVersion, classVisitor);
        // 删除字段
        classVisitor = new MyClassVisitor3(apiVersion, classVisitor);
        // 添加字段
        classVisitor = new MyClassVisitor4(apiVersion, classVisitor);
        // 删除方法
        classVisitor = new MyClassVisitor5(apiVersion, classVisitor);
        // 增加方法
        classVisitor = new MyClassVisitor6(apiVersion, classVisitor);
        classVisitor = new MyClassVisitor7(apiVersion, classVisitor);
        // 运行的时候 方法倒序调用 6>5>4>3>2>1
        classReader.accept(classVisitor, ClassReader.EXPAND_FRAMES | ClassReader.SKIP_DEBUG);
        byte[] classByte = classWriter.toByteArray();
        if (CHECK && END_CHECK) {
            CheckClassAdapter.verify(new ClassReader(classByte), false, new PrintWriter(System.out));
        }
        writeClassFileCore(classByte, getClassFile());
    }

    private static File getClassFile() {
        String className = "HelloWordModifyClass";
        File file = new File(ClassFileUtil.getClassFileModelPath(), className + ".class");
        return file;
    }

    private static void writeClassFileCore(byte[] core, File classFilePath) {
        ClassFileUtil.classFileCoreWrite(core, classFilePath);
    }

}
